﻿//同步socket收发

using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using ZDK.Infra.Services;

namespace ZDK.Utilities
{
    public class SyncSocket
    {
        IMyLog _log;
        string _serverIp;
        int _serverPort;
        int _timeoutMSec = 3000;
        Socket _tcpSync = null;
        byte[] _tcpSyncBuffer = new byte[512000];
        public bool IsClosed { get => (_tcpSync == null || _tcpSync.Connected == false); }
        object _async = new object(); //读写方法的锁
        readonly static ManualResetEvent TimeoutObject = new ManualResetEvent(false);

        public SyncSocket(IMyLog log, string ip, int port, int timeoutMSec = 3000)
        {
            _log = log;
            _serverIp = ip;
            _serverPort = port;
            _timeoutMSec = timeoutMSec;
        }

        #region Connect 连接（有超时）
        public bool Connect()
        {
            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(_serverIp), _serverPort);
            TimeoutObject.Reset();
            _tcpSync = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _tcpSync.SendTimeout = _timeoutMSec;
            _tcpSync.ReceiveTimeout = _timeoutMSec;
            _tcpSync.NoDelay = true;
            _tcpSync.BeginConnect(remoteEndPoint, CallBackMethod, _tcpSync);
            //阻塞当前线程           
            if (TimeoutObject.WaitOne(_timeoutMSec, false))
            {
                return true;
            }
            else
            {
                _log.Error($"{_serverIp}:{_serverPort} 连接超时！");
                return false;
            }
        }
        // Connect的异步回调方法       
        void CallBackMethod(System.IAsyncResult asyncresult)
        {
            TimeoutObject.Set();//使阻塞的线程继续  
        }
        #endregion


        #region WriteSyncData socket 同步写数据
        public byte[] WriteSyncData(byte[] data)
        {
            if (IsClosed)
            {
                Connect();
            }
            lock (_async)
            {
                try
                {
                    _tcpSync.Send(data, 0, data.Length, SocketFlags.None);
                    int result = _tcpSync.Receive(_tcpSyncBuffer, 0, _tcpSyncBuffer.Length, SocketFlags.None);

                    if (result <= 0)
                    {
                        _log.Warn("接收数据错误!");
                        return null;
                    }
                    int len = result;
                    return _tcpSyncBuffer.Take(len).ToArray();
                }
                catch (Exception ex)
                {
                    _log.Error($"发送数据异常：{ex.Message}");
                }
            }
            return null;
        }

        #endregion
    }
}
